package com.hik.rpq.proxy.FactoryProxy.example.cart;

import com.hik.rpq.proxy.FactoryProxy.example.entity.Cart;
import com.hik.rpq.proxy.FactoryProxy.example.entity.Item;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * cart 抽象类
 * 用于提取重复代码 , 子类只关注自己的业务代码
 *
 * 这种设计模式 是模板方法
 * @author renpeiqian
 * @date 2021/8/19 10:00
 * @since
 */
public abstract class AbstractCart {

    public Cart process(long userId, Map<Long,Integer> items){
        Cart cart = new Cart();

        List<Item> itemList  =new ArrayList<>();

        //map 2 item
        items.entrySet().stream().forEach( entry-> {
            Item item = new Item();
            item.setId(entry.getKey());
            item.setQuantity(entry.getValue());
            item.setPrice(new BigDecimal("52"));
            itemList.add(item);
        });
        cart.setItems(itemList);

        //处理商品优惠及运费
        itemList.stream().forEach( item -> {
            //定义抽象方法 ，不同的子类实现不同的逻辑。
            processCouponPrice(userId, item);

            processDeliveryPrice(userId, item);
        });


        //商品总价

        cart.setTotalItemPrice(cart.getItems().stream().map(item -> item.getPrice().multiply(BigDecimal.valueOf(item.getQuantity()))).reduce(BigDecimal.ZERO, BigDecimal::add));

        //计算运费总价
        cart.setTotalDeliveryPrice(cart.getItems().stream().map(Item::getDeliveryPrice).reduce(BigDecimal.ZERO, BigDecimal::add));

        //计算总优惠
        cart.setTotalDiscount(cart.getItems().stream().map(Item::getCouponPrice).reduce(BigDecimal.ZERO, BigDecimal::add));

        //应付总价=商品总价+运费总价-总优惠
        cart.setPayPrice(cart.getTotalItemPrice().add(cart.getTotalDeliveryPrice()).subtract(cart.getTotalDiscount()));

        return cart;
    }

    /**
     * 计算对应用户的运费优惠
     * @param userId
     * @param  item
     * @return void
     */
    protected abstract void processDeliveryPrice(long userId, Item item);

    /**
     * 计算对应用户的商品优惠
     * @param userId
     * @param  item
     * @return void
     */
    protected abstract void processCouponPrice(long userId, Item item);


}
